#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMimeData>
#include <QDrag>
#include <QPixmap>
#include <QPainter>
#include <QPen>
#include <QLabel>
#include <random>
#include <QTime>
#include <QRegularExpression>
#include <QLabel>
#include "minet_dev.h"

#include <QDebug>

#define LABEL_SIZE (20)

static QString hotSpotMimeDataKey() { return QStringLiteral("application/x-hotspot"); }

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setWindowTitle(QString(tr("Emulation minet")));

    isShowDist = true;
    node = 0;
    timer1ms = new QTimer(this);
    connect(timer1ms, SIGNAL(timeout()), this, SLOT(timer1msExpire()));
    devs.clear();

    setAcceptDrops(true);

    connect(ui->addNode,SIGNAL(toggled(bool)),this,SLOT(addNewNode(bool)));
    connect(ui->clrNode,SIGNAL(toggled(bool)),this,SLOT(clrNode(bool)));
    connect(ui->actionNetStart,SIGNAL(toggled(bool)),this,SLOT(startNet(bool)));
    connect(ui->actionNetStop,SIGNAL(toggled(bool)),this,SLOT(stopNet(bool)));
}

MainWindow::~MainWindow()
{
    delete ui;

    delete timer1ms;
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPen pen;

    foreach (QLabel *node, findChildren<QLabel *>()) {
        if (node->isVisible()) {
            pen.setColor(QColor(0,0,0));
//            pen.setWidth(10);
            painter.setPen(pen);
            QPoint point = node->pos();
            point.setX(point.x() + (LABEL_SIZE>>1));
            point.setY(point.y() + (LABEL_SIZE>>1));
            painter.drawEllipse(point, (LABEL_SIZE>>1), (LABEL_SIZE>>1));

            if (this->isShowDist) {
                pen.setColor(QColor(0,0,255));
                painter.setPen(pen);
                painter.drawEllipse(point, (NODE_WIRELESS_DISTANCE), (NODE_WIRELESS_DISTANCE));
            }
        } else {
            node->deleteLater();
        }
    }
}

void MainWindow::timer1msExpire()
{
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    QLabel *child = qobject_cast<QLabel*>(childAt(event->pos()));
    if (!child) {
        return;
    }

    QPoint hotSpot = event->pos() - child->pos();
    QMimeData *mimeData = new QMimeData;
    mimeData->setText(child->text());
    mimeData->setData(hotSpotMimeDataKey(),
                      QByteArray::number(hotSpot.x()) + ' ' + QByteArray::number(hotSpot.y()));

    QPixmap pixmap(child->size());
    child->render(&pixmap);

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->setPixmap(pixmap);
    drag->setHotSpot(hotSpot);

    Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);

    if (dropAction == Qt::MoveAction) {
        child->close();
    }
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    update();
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasText()) {
        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            event->accept();
        } else {
            event->acceptProposedAction();
        }
    } else {
        event->ignore();
    }

    update();
}

void MainWindow::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasText()) {
        const QMimeData *mime = event->mimeData();
        QStringList pieces = mime->text().split(QRegularExpression(QStringLiteral("\\s+")),QString::SkipEmptyParts);

        QPoint position = event->pos();
        QPoint hotSpot;

        QByteArrayList hotSpotPos = mime->data(hotSpotMimeDataKey()).split(' ');
        if (hotSpotPos.size() == 2) {
            hotSpot.setX(hotSpotPos.first().toInt());
            hotSpot.setY(hotSpotPos.last().toInt());
        }

        foreach (const QString &piece, pieces) {
            QLabel *node = new QLabel(piece, this);
            node->setFixedWidth(LABEL_SIZE);
            node->setFixedHeight(LABEL_SIZE);
            node->setAlignment(Qt::AlignCenter);
            node->move(position - hotSpot);
            node->show();
            node->setAttribute(Qt::WA_DeleteOnClose);

            position += QPoint(node->width(), 0);

            uint16_t SA = node->text().toUShort();
            for (MiNetDev *dev: devs) {
                if (SA == dev->addr()) {
                    QPoint pos = node->pos();
                    dev->posUpdate(pos);
                    break;
                }
            }
        }

        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            event->accept();
        } else {
            event->acceptProposedAction();
        }
    } else {
        event->ignore();
    }

    foreach (MainWindow *widget, findChildren<MainWindow *>()) {
        if (!widget->isVisible())
            widget->deleteLater();
    }

    foreach (QLabel *node, findChildren<QLabel *>()) {
        if (!node->isVisible()) {
            node->deleteLater();
        }
    }

    update();
}

void MainWindow::addNewNode(bool tog)
{
    if (tog) {
        ui->addNode->setChecked(false);
    } else {
        QLabel *node = new QLabel(QString::number(this->node, 10), this);
        node->move(qrand() % this->geometry().width(), qrand() % this->geometry().height());
        node->setFixedWidth(LABEL_SIZE);
        node->setFixedHeight(LABEL_SIZE);
        node->setAlignment(Qt::AlignCenter);
        node->show();
        node->setAttribute(Qt::WA_DeleteOnClose);

        QPoint pos = node->pos();
        uint16_t SA = this->node;
        MiNetDev *dev = new MiNetDev(pos, SA, 1);
        devs.append(dev);
        this->node += 1;
    }

    update();
}

void MainWindow::clrNode(bool tog)
{
    node = 0;

    if (tog) {
        ui->clrNode->setChecked(false);
    } else {
        foreach (QLabel *node, findChildren<QLabel *>()) {
            node->deleteLater();
        }
    }

    for (MiNetDev *dev: devs) {
        delete dev;
    }

    minet_simdev_init();
    devs.clear();

    update();
}

void MainWindow::startNet(bool tog)
{
    update();

    isShowDist = false;
    timer1msCnt = 0;
    if (tog) {
        timer1ms->start(1);
        ui->actionNetStart->setChecked(false);

        for (MiNetDev *dev: devs) {
            dev->start();
        }
    } else {
    }
}

void MainWindow::stopNet(bool tog)
{
    update();

    isShowDist = true;
    timer1msCnt = 0;
    if (tog) {
        timer1ms->stop();
        ui->actionNetStop->setChecked(false);

        for (MiNetDev *dev: devs) {
            dev->terminate();
        }
        simlock = 0;
    } else {
    }
}

void MainWindow::on_pushButton_clicked()
{
    update();

    foreach (QLabel *node, findChildren<QLabel *>()) {
        if (node->isVisible()) {
            qDebug() << "text: " << node->text() << node->pos();
        }
    }

    qDebug() << "";
    for (MiNetDev *dev: devs) {
        qDebug() << "MiNetDev: " << dev->addr() << "," << dev->posGet();
    }
}

void MainWindow::on_pushButtonTst_clicked()
{
}
